#include "mycal.h"
#include "widget.h"
#include <QDebug>

int factorical(int n){
    return n>1?factorical(n-1)*n:1;
}

double jisuan(double a,double b,char c)
{
    switch(c){
    case '+':
        return a+b;
    case '-':
        return a-b;
    case '*':
        return a*b;
    case '/':
        return a/b;
    case '^':
        return pow(a,b);
    }
}

double sjisuan(double a,char b){
    switch (b) {
    case 's':
        return sin(a);
    case 'c':
        return cos(a);
    case 't':
        return tan(a);
    case 'a':
        return asin(a);
    case 'b':
        return acos(a);
    case 'd':
        return atan(a);
    case 'I':
        return log(a);
    case '_':
        return sqrt(a);
    case '!':
        return (double)factorical((int)a);
    }
}

int youxj(char c)
{
    switch(c){
    case '+':
    case '-':return 1;
    case '*':
    case '/':return 2;
    case '^':return 3;
    case 's':
    case 'c':
    case 't':
    case 'a':
    case 'b':
    case 'd':
    case 'I':
    case '_':
    case '!':return 4;
    }
}

double cal(QString str)
{
    QStack<double> nStack;
    QStack<char> cStack;
    int pos=0;

    while(true){
        QString t;
        for(;;pos++){
            if(pos>=str.length()){
                nStack.push(t.toDouble());
                t.clear();
                break;
            }
            if((str[pos]>='0'&&str[pos]<='9')||str[pos]=='.'||
                    (pos!=0&&str[pos-1]=='('&&str[pos]=='-')||(pos==0&&str[pos]=='-')){
                t+=str[pos];
            }else {
                QString t_;
                t_.clear();
                if(t==t_){
                    break;
                }else{
                    nStack.push(t.toDouble());
                }
                t.clear();
                break;
            }
        }
        t+=str[pos];
        QByteArray ba=t.toLatin1();
        while(pos<str.length()){
            if(cStack.empty()){
                cStack.push(ba[0]);
            }else if(str[pos]==')'){
                while(true){
                    char c=cStack.pop();
                    if(c=='('){
                        break;
                    }else if(youxj(c)==4){
                        double a=nStack.pop();
                        nStack.push(sjisuan(a,c));
                    }else{
                        double a=nStack.pop(),b=nStack.pop();
                        nStack.push(jisuan(b,a,c));
                    }
                }
            }else if(cStack.back()=='('){
                cStack.push(ba[0]);
            }else if(str[pos]=='('){
                cStack.push(ba[0]);
            }else if(youxj(cStack.back())>=youxj(ba[0])){
                char c=cStack.pop();
                if(youxj(c)==4){
                    double a=nStack.pop();
                    nStack.push(sjisuan(a,c));
                }else{
                    double a=nStack.pop(),b=nStack.pop();
                    nStack.push(jisuan(b,a,c));
                }
                continue;
            }else if(youxj(cStack.back())<youxj(ba[0])){
                cStack.push(ba[0]);
            }
            t.clear();
            pos++;
            break;
        }
        if(pos>=str.length()){

            while(!cStack.empty()){
                char c=cStack.pop();
                if(youxj(c)==4){
                    double a=nStack.pop();
                    nStack.push(sjisuan(a,c));
                }else{
                    double a=nStack.pop(),b=nStack.pop();
                    nStack.push(jisuan(b,a,c));
                }
            }
            break;
        }
    }
    return nStack.pop();
}
